package simulaco.business;

import gminet.infra.business.BusinessException;
import gminet.infra.business.BusinessObject;
import gminet.infra.db.Transaction;
import gminet.infra.db.TransactionException;
import gminet.infra.toolkit.DateToolkit;
import gminet.infra.toolkit.NumberToolkit;
import gminet.infra.toolkit.StringToolkit;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import simulaco.dao.ConcursoDAO;
import simulaco.dao.ConcursoFilter;
import simulaco.dao.CargoDAO;
import simulaco.dao.CargoFilter;
import simulaco.dto.Cargo;
import simulaco.dto.Situacao;

public class CargoBusiness extends BusinessObject {

    private static List<Cargo> CACHE_LIST_CARGOS = null;
    private static List<Cargo> CACHE_LIST_CARGOS_ACTIVES = null;

    public static Cargo findByPK(int cargoId) throws TransactionException {

        Cargo cargo = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            cargo = CargoDAO.findByPK(cargoId, conn);
        } finally {
            transaction.release();
        }
        return cargo;
    }

    public static List<Cargo> findAll() throws TransactionException {

        if (CACHE_LIST_CARGOS == null || CACHE_LIST_CARGOS.size() == 0) {
            List<Cargo> cargos = null;
            Transaction transaction = createTransaction();
            try {
                Connection conn = transaction.getConnection();
                cargos = CargoDAO.findAll(conn);
            } catch (TransactionException te) {
                transaction.rollback();
                throw te;
            } finally {
                transaction.release();
            }
            // CACHE
            if (CACHE_LIST_CARGOS == null) {
                CACHE_LIST_CARGOS = new ArrayList<Cargo>();
            }
            CACHE_LIST_CARGOS.addAll(cargos);
        }
        return CACHE_LIST_CARGOS;
    }

    public static List<Cargo> findActives() throws TransactionException {

        if (CACHE_LIST_CARGOS_ACTIVES == null || CACHE_LIST_CARGOS_ACTIVES.size() == 0) {
            List<Cargo> cargos = null;
            Transaction transaction = createTransaction();
            try {
                Connection conn = transaction.getConnection();
                CargoFilter filter = new CargoFilter();
                filter.setCodigoSituacao(Situacao.HABILITADO.getCodigo());
                cargos = CargoDAO.findByFilter(filter, conn);
            } catch (TransactionException te) {
                transaction.rollback();
                throw te;
            } finally {
                transaction.release();
            }
            // CACHE
            if (CACHE_LIST_CARGOS_ACTIVES == null) {
                CACHE_LIST_CARGOS_ACTIVES = new ArrayList<Cargo>();
            }
            CACHE_LIST_CARGOS_ACTIVES.addAll(cargos);
        }
        return CACHE_LIST_CARGOS_ACTIVES;
    }

    public static Cargo insert(Cargo cargo) throws BusinessException, TransactionException {

        Cargo newCargo = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // CONCURSO
            Date dataAtual = DateToolkit.getDate();
            int rangeId = createRangeId(cargo.getNome());
            cargo.setCodigo(CargoDAO.getNextCodigo(conn, rangeId, rangeId + 1000));
            if (cargo.getSituacao().getCodigo() == 0) {
                cargo.setSituacao(Situacao.DESABILITADO);
            }
            cargo.setDataCadastro(dataAtual);
            CargoDAO.insert(cargo, conn);
            // COMMIT
            transaction.commit();
            // RELEASE CACHE
            releaseCache();
            //
            newCargo = cargo;
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return newCargo;
    }

    private static int createRangeId(String cargoName) {

        String strCodigo = "1";
        String caracter1 = cargoName.substring(0, 1).toUpperCase();
        String caracter2 = cargoName.length() > 1 ? cargoName.substring(1, 2).toUpperCase() : "A";
        int valor1 = Math.abs(caracter1.compareTo("A") + 1);
        if (StringToolkit.isDigit(caracter1)) {
            valor1 = 0;
        }
        int valor2 = Math.abs(caracter2.compareTo("A") / 3);
        if (StringToolkit.isDigit(caracter2)) {
            valor2 = 0;
        }
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor1, 99), 2);
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor2, 9), 1);
        strCodigo += "000";
        return Integer.parseInt(strCodigo);
    }

    public static void update(Cargo cargo) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            CargoDAO.update(cargo, conn);
            // COMMIT
            transaction.commit();
            // RELEASE CACHE
            releaseCache();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void updateStatus(Cargo cargo) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            Cargo auxCargo = CargoDAO.findByPK(cargo.getCodigo(), conn);
            auxCargo.setSituacao(cargo.getSituacao());
            CargoDAO.update(auxCargo, conn);
            // COMMIT
            transaction.commit();
            // RELEASE CACHE
            releaseCache();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void delete(Cargo cargo) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // VERIFICA SE TEM CONCURSO VINCULADOS
            ConcursoFilter filter = new ConcursoFilter();
            filter.setCodigoCargo(cargo.getCodigo());
            if (ConcursoDAO.findByFilter(filter, conn).size() > 0) {
                throw new BusinessException("Não é possivel excluir este cargo. Existem concursos vinculados.");
            } else {
                // EXCLUI O CARGO
                CargoDAO.delete(cargo, conn);
                transaction.commit();
                // RELEASE CACHE
                releaseCache();
            }
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    private static void releaseCache() {

        // CACHE_LIST_CARGOS
        if (CACHE_LIST_CARGOS != null) {
            CACHE_LIST_CARGOS.clear();
        }
        CACHE_LIST_CARGOS = null;
        // CACHE_LIST_CARGOS_ACTIVES
        if (CACHE_LIST_CARGOS_ACTIVES != null) {
            CACHE_LIST_CARGOS_ACTIVES.clear();
        }
        CACHE_LIST_CARGOS_ACTIVES = null;
    }

}
